﻿using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using AFT.Parking.Bizlogic.Parkings;
using AFT.Parking.Entity;
using AFT.Parking.Foundation.Calculate;
using AFT.Parking.WebSite.Filter;
using AFT.Parking.WebSite.Models;
using Newtonsoft.Json;

namespace AFT.Parking.WebSite.Controllers
{
    [AdminOnly]
    public class MarkCoordinatesController : BaseController
    {
        //
        // GET: /MarkCoordinates/
        private readonly ParkingBiz _parkingBiz;

        public MarkCoordinatesController()
        {
            _parkingBiz = new ParkingBiz();
        }

        public ActionResult MarkCoordinates(int id)
        {
            ViewBag.id = id;

            return View();
        }

        public ActionResult GetParkLocations(int areaId, int locationId)
        {
            var locations = _parkingBiz.SameAreasLocations(areaId, locationId).Select(p => new { p.Id, p.Name });
            return Json(locations, "application/json", JsonRequestBehavior.AllowGet);
        }

        [HttpPost]
        public ActionResult Coordinates(int id)
        {
            var parkArea = _parkingBiz.GetParkingArea(id);
            var parkLocation = _parkingBiz.SameAreasLocations(id);
            var cdn = new Coordinate
            {
                Id = id,
                ProjectImgUrl = parkArea.ImgUrl,
                Shapes = DeserializeObject<List<Shape>>(parkArea.Shapes),
                Markers = parkLocation.Select(p => new Marker
                {
                    Id = p.Id,
                    Name = p.Name,
                    IsEnable = p.IsEnable,
                    IsFork = p.IsFork,
                    IsLift = p.IsLift,
                    ScanCode = GetScanCode(p.Id),
                    PrintScanCodeCount = p.PrintScanCodeCount,
                    AccessTo = DeserializeObject<List<AccessTo>>(p.AccessTo).Select(a => a.Id).ToArray(),
                    Offset = new Offset { Left = p.LocationX, Top = p.LocationY },
                    Position = new Position { Left = p.LocationX, Top = p.LocationY }
                }).ToList()
            };
            return Json(cdn, "application/json");
        }

        [HttpPost]
        public ActionResult EditCoordinate(Coordinate pc)
        {
            var parkArea = _parkingBiz.GetParkingArea(pc.Id);
            parkArea.Shapes = SerializeObject(pc.Shapes);
            _parkingBiz.EditeParkingArea(parkArea);

            var oldParkingLocation = _parkingBiz.SameAreasLocations(pc.Id);
            var nowParkingLocationIds = pc.Markers.Select(u => u.Id);
            var deleteParkingLocation = oldParkingLocation.Where(u => !nowParkingLocationIds.Contains(u.Id));
            foreach (var item in deleteParkingLocation)
            {
                _parkingBiz.DeleteParkingLocation(item.Id);
                _parkingBiz.DeleteScanCodeAndLocation(
                    u => u.LocationId == item.Id && u.LocationType == (int)Parking.Entity.Enums.LocationTypes.停车区);
            }
            //foreach (var m in pc.Markers)
            //{
            //    var pl = parkLocation.FirstOrDefault(p => p.Id == m.Id) ?? new ParkingLocation();

            //    pl.IsEnable = m.IsEnable;
            //    pl.IsFork = m.IsFork;
            //    pl.LocationX = m.Position.Left;
            //    pl.LocationY = m.Position.Top;
            //    pl.Name = m.Name;
            //    pl.ParkingAreaId = pc.Id;
            //    pl.AccessTo = CalculateWeight(m, pc.Markers);
            //    SaveParkingLocation(pl);
            //}
            return Json(true, "application/json");
        }

        [HttpPost]
        public ActionResult SaveMarker(int parkingAreaId, Marker marker)
        {
            var parkLocation = _parkingBiz.SameAreasLocations(parkingAreaId);
            var pl = parkLocation.FirstOrDefault(p => p.Id == marker.Id) ?? new ParkingLocation();
            if (marker.AccessTo != null && marker.AccessTo.Length > 0)
            {
                var acts = parkLocation.Where(p => marker.AccessTo.Contains(p.Id)).Select(a => new AccessTo
                {
                    Id = a.Id,
                    Weight =
                        Distance.GetDistanceOfPoint(marker.Position.Left, marker.Position.Top, a.LocationX, a.LocationY)
                }).ToList();
                pl.AccessTo = SerializeObject(acts);
            }
            else
                pl.AccessTo = string.Empty;
            pl.IsEnable = marker.IsEnable;
            pl.IsFork = marker.IsFork;
            pl.IsLift = marker.IsLift;
            pl.LocationX = marker.Position.Left;
            pl.LocationY = marker.Position.Top;
            pl.Name = marker.Name;
            pl.PrintScanCodeCount = marker.PrintScanCodeCount;
            pl.ParkingAreaId = parkingAreaId;

            SaveParkingLocation(pl);
            return Json(true, "application/json");
        }

        private int GetScanCode(int locationId)
        {
            var scanCode = _parkingBiz.GetScanCodeByLocationId(locationId, (int)Entity.Enums.LocationTypes.停车区);
            return scanCode != null ? scanCode.Id : 0;
        }

        private void SaveParkingLocation(ParkingLocation pl)
        {
            if (pl.Id == 0)
            {
                _parkingBiz.AddParkingLocation(pl);
            }
            else
            {
                _parkingBiz.EditeParkingLocation(pl);
            }
        }

        #region Calculate Weight
        private static string CalculateWeight(Marker from, IEnumerable<Marker> markers)
        {
            if (from.AccessTo == null) return "[]";
            var acts = markers
                .Where(t => from.AccessTo.Contains(t.Id))
                .Select(to => new AccessTo
                {
                    Id = to.Id,
                    Weight = Distance.GetDistanceOfPoint(from.Position.Left, from.Position.Top, to.Position.Left, to.Position.Top)
                }).ToList();
            return SerializeObject(acts);
        }
        #endregion

        #region Json Serialize & Deserialize
        private static T DeserializeObject<T>(string value) where T : new()
        {
            return string.IsNullOrWhiteSpace(value) ? new T() : JsonConvert.DeserializeObject<T>(value);
        }

        private static string SerializeObject(object value)
        {
            return JsonConvert.SerializeObject(value);
        }
        #endregion
    }
}